package root.electronclass.electronclass.grade.widget

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import root.electronclass.electronclass.R
import java.util.Locale
import kotlin.math.cos
import kotlin.math.sin
import kotlin.random.Random

/**
 *
 * @author Lokiy
 * @date 2023/3/11 13:59
 */
class CircleChart : View {

    private val values = mutableListOf<CircleItem>()
    private val paint = Paint().apply {
        style = Paint.Style.FILL
    }
    var progressWidth = 0f
        set(value) {
            field = value
            paint.strokeWidth = value
        }
    private val linePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.WHITE
        strokeWidth = 5f
        style = Paint.Style.STROKE
    }
    private val textPaint = Paint().apply {
        isAntiAlias = true
        style = Paint.Style.FILL
        color = -1
    }
    var textSize = 0f
        set(value) {
            field = value
            textPaint.strokeWidth = value
        }
    private val rectF = RectF()

    var textFormatter: (Int) -> String = { it.toString() }

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, attrStyle: Int) : super(context, attrs, 0) {
        context.obtainStyledAttributes(attrs, R.styleable.CircleChart).also {
            progressWidth = it.getDimension(
                R.styleable.CircleChart_progressWidth,
                -1f
            )
            textSize = it.getDimension(
                R.styleable.CircleChart_android_textSize,
                12f
            )
        }.recycle()
        paint.strokeWidth = progressWidth
        textPaint.textSize = textSize
        if (isInEditMode) {
            for (i in (0..3)) {
                values.add(CircleItem(Color.rgb(Random.nextInt(255), Random.nextInt(255), Random.nextInt(255)), Random.nextInt(1000)))
            }
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)

        if (progressWidth == -1f) {
            progressWidth = width.coerceAtMost(height) / 2f
        }
    }

    fun setData(list: List<CircleItem>) {
        values.clear()
        values.addAll(list)
        invalidate()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (values.isEmpty()) return

        val w = width.toFloat()
        val h = height.toFloat()
        val maxR = width.coerceAtMost(height) / 2f
        val r = w.coerceAtMost(h) / 2 * 0.9f
        val cx = w / 2
        val cy = h / 2
        rectF.set(cx - r, cy - r, cx + r, cy + r)

        val total = values.sumOf { it.count }
        if (total == 0) return

        var startAngle = -90f
        linePaint.strokeWidth = 5f
        values.forEachIndexed { index, item ->
            val sweepAngle = item.count.toFloat() / total * 360f
            paint.color = item.color
            canvas.drawArc(rectF, startAngle, sweepAngle, true, paint)
            // 画分割线
            if (index != values.size - 1) {
                val angleRad = Math.toRadians((startAngle + sweepAngle).toDouble())
                val x = cx + r * cos(angleRad).toFloat()
                val y = cy + r * sin(angleRad).toFloat()
                canvas.drawLine(cx, cy, x, y, linePaint)
            }
            startAngle += sweepAngle
        }

        // 画第一个分割线
        linePaint.strokeWidth = 2f
        val firstAngleRad = Math.toRadians(-90.0)
        val x0 = cx + r * cos(firstAngleRad).toFloat()
        val y0 = cy + r * sin(firstAngleRad).toFloat()
        canvas.drawLine(cx, cy, x0, y0, linePaint)

        val centerR = maxR - progressWidth
        if (centerR > 0f) {
            //绘制中间的白色圆
            rectF.set(cx - centerR, cy - centerR, cx + centerR, cy + centerR)
            paint.color = Color.WHITE
            canvas.drawArc(rectF, 0f, 360f, true, paint)
        }

        // 画百分比文字
        startAngle = -90f
        val ratio = if (progressWidth == maxR) 0.6f else (1 - (progressWidth / maxR) / 2).coerceAtLeast(0.6f)
        values.forEach { item ->
            val sweepAngle = item.count.toFloat() / total * 360f
            val percent = item.count.toFloat() / total * 100
            val text = String.format(Locale.getDefault(), "%.1f%%", percent)
            val angle = startAngle + sweepAngle / 2
            val angleRad = Math.toRadians(angle.toDouble())
            val textWidth = textPaint.measureText(text)
            val tx = cx + r * ratio * cos(angleRad).toFloat() - textWidth / 2
            val ty = cy + r * ratio * sin(angleRad).toFloat() + textPaint.textSize / 3
            canvas.drawText(text, tx, ty, textPaint)
            startAngle += sweepAngle
        }
    }

}

data class CircleItem(val color: Int, val count: Int)